package com.macrounion.atv.processor;

import com.github.pagehelper.Page;
import com.google.common.collect.Lists;
import com.macrounion.atv.config.FileConfig;
import com.macrounion.atv.service.dto.ProtocolONIDto;
import com.macrounion.atv.service.entity.Net;
import com.macrounion.atv.service.entity.ProtocolC;
import com.macrounion.atv.service.entity.ext.ProtocolExt;
import com.macrounion.atv.service.entity.ext.ProtocolOutExt;
import com.macrounion.atv.service.service.ProtocolCService;
import com.macrounion.atv.utils.SimpleCsvUtils;
import com.macrounion.atv.service.utils.XmlUtils;
import com.macrounion.base.service.dto.PageRespDto;
import com.macrounion.base.service.dto.StringRespDto;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.macrounion.atv.service.entity.Protocol;
import com.macrounion.atv.service.service.ProtocolService;
import com.macrounion.base.processor.BaseProcessor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;

@Component
public class ProtocolProcessor extends BaseProcessor<Protocol, ProtocolExt, ProtocolService, Protocol> {

    @Autowired
    ProtocolCProcessor protocolCProcessor;
    @Autowired
    FileConfig customConfig;
    @Autowired
    private ProtocolCService protocolCService;

    public Map<String, List<ProtocolC>> getProtocolMap(List<String> pids) {
        return service.getProtocolMap(pids);
    }

    public List<Net> getNets() {
        return service.getNets();
    }

    public PageRespDto<ProtocolExt> requestPageExt(Protocol p) {
        PageRespDto<ProtocolExt> pageResp = new PageRespDto();
        Page<ProtocolExt> page = service.requestPageExt(R2E(p));
        if (page == null) {
            return pageResp;
        } else {
            BeanUtils.copyProperties(page, pageResp);
            if (CollectionUtils.isEmpty(page.getResult())) {
                return pageResp;
            } else {
                pageResp.setDataList(MES2RS(page.getResult()));
                return pageResp;
            }
        }
    }

    @Transactional
    public StringRespDto removeProtocol(String protocolId) {
        if (checkIsUsed(protocolId)) {
            return new StringRespDto("存在引用该协议的设备，不能删除！");
        }
        boolean remove = this.service.removeById(protocolId);
        if (remove) {
            int rows = protocolCProcessor.deleteByProtocolId(protocolId);
            if (rows >= 0) {
                return new StringRespDto("删除成功！");
            } else {
                return new StringRespDto("删除失败！");
            }
        } else {
            return new StringRespDto("删除失败！");
        }
    }

    public int saveProtocols(List<Protocol> protocols) {
        return this.service.saveProtocols(protocols);
    }

    public StringRespDto importProtocolsCsv(MultipartFile file) {
        if (file.isEmpty()) {
            return new StringRespDto("文件上传失败，请稍后再试！");
        }
        ProtocolONIDto protocolONIDto = null;
        try {
            protocolONIDto = SimpleCsvUtils.csv2Protocol(file);
        } catch (IOException e) {
            e.printStackTrace();
            return new StringRespDto("导入失败！文件内容或格式可能存在错误！");
        }
        if (protocolONIDto.getProtocol() == null) {
            return new StringRespDto("导入失败！文件内容或格式可能存在错误！");
        } else if (protocolONIDto.getProtocol().getName() == null || "".equals(protocolONIDto.getProtocol().getName())) {
            protocolONIDto.getProtocol().setName(UUID.randomUUID().toString().substring(20));
        }
        int count = this.service.getCountByName(protocolONIDto.getProtocol().getName());
        if (count >= 1) {
            return new StringRespDto("存在重复的协议名！建议修改协议名：" + protocolONIDto.getProtocol().getName());
        }
        boolean insertResult = insertProtocolsNProtocols(protocolONIDto);
        if (insertResult) {
            return new StringRespDto("导入成功！");
        } else {
            return new StringRespDto("协议详情导入失败！");
        }
    }

    /**
     * 导入xml格式的协议文件
     *
     * @param xml
     * @return
     */
    public StringRespDto importProtocols(String xml) {
        if (xml.isEmpty()) return new StringRespDto("文件为空");

        ProtocolONIDto protocolONIDto = null;
        try {
            protocolONIDto = XmlUtils.convertToJava(xml, ProtocolONIDto.class);
        } catch (Exception e) {
            e.printStackTrace();
            return new StringRespDto("导入失败！文件内容或格式可能存在错误！");
        }
        if (protocolONIDto.getProtocol() == null) {
            return new StringRespDto("导入失败！文件内容或格式可能存在错误！");
        } else if (protocolONIDto.getProtocol().getName() == null || "".equals(protocolONIDto.getProtocol().getName())) {
            protocolONIDto.getProtocol().setName(UUID.randomUUID().toString().substring(20));
        } else {
            int count = this.service.getCountByName(protocolONIDto.getProtocol().getName());
            if (count >= 1) {
                return new StringRespDto("存在重复的协议名！建议修改协议名：" + protocolONIDto.getProtocol().getName());
            }
        }
        if (null != protocolONIDto) {
            boolean insertResult = insertProtocolsNProtocols(protocolONIDto);
            if (insertResult) {
                return new StringRespDto("导入成功！");
            } else {
                return new StringRespDto("协议详情导入失败！");
            }
        } else {
            return new StringRespDto("导入失败！文件内容或格式可能存在错误！");
        }
    }

    /**
     * 导入协议
     *
     * @param protocolONIDto
     * @return
     */
    @Transactional
    public boolean insertProtocolsNProtocols(ProtocolONIDto protocolONIDto) {
        List<Protocol> protocolList = new ArrayList<>();
        List<ProtocolC> protocolCS = new ArrayList<>();
        Protocol protocol = protocolONIDto.getProtocol();
        String protocolId = UUID.randomUUID().toString();
        protocol.setId(protocolId);
        protocol.setCreatedTime(new Date());
        protocolList.add(protocol);
        List<ProtocolC> protocolCList = protocolONIDto.getProtocolCList();
        if (protocolList.size() > 0) {
            int i = saveProtocols(protocolList);
            if (null == protocolCList || protocolCList.size() == 0) {
                return true;
            }
            if (i > 0) {
                for (ProtocolC protocolC : protocolCList) {
                    protocolC.setId(UUID.randomUUID().toString());
                    protocolC.setCreatedTime(new Date());
                    protocolC.setProtocolName(protocol.getName());
                    protocolC.setProtocolId(protocol.getId());
                    protocolCS.add(protocolC);
                }
                protocolCProcessor.saveProtocols(protocolId, protocolCS);
            } else {
                return false;
            }
        }
        return true;
    }

    public List<Protocol> getProtocolListByType(String type) {
        return service.getProtocolByType(type);
    }

    private List<ProtocolOutExt> getProtocolOutDest(String protocolId) {
        return service.getProtocolOut(protocolId);
    }

    /**
     * 封装协议输出对象
     *
     * @param protocolId
     * @return
     */
    public ProtocolONIDto getProtocolOut(String protocolId) {
        ProtocolONIDto protocolONIDto = new ProtocolONIDto();
        List<ProtocolOutExt> protocolOutDestList = getProtocolOutDest(protocolId);
        Protocol protocol = new Protocol();
        List<ProtocolC> protocolCList = new ArrayList<>();
        if (protocolOutDestList != null) {
            ProtocolOutExt dest = protocolOutDestList.get(0);
            protocol.setName(dest.getName());
            protocol.setRemark(dest.getRemark());
            protocol.setSnmpv(dest.getSnmpv());
            protocol.setStype(dest.getStype());
            protocolONIDto.setProtocol(protocol);
            if (dest.getMid() != null) {
                for (ProtocolOutExt protocolOutExt : protocolOutDestList) {
                    ProtocolC protocolC = new ProtocolC();
                    protocolC.setMid(protocolOutExt.getMid());
                    protocolC.setChannelCode(protocolOutExt.getChannelCode());
                    protocolC.setName(protocolOutExt.getProtocolCName());
                    protocolC.setUnit(protocolOutExt.getUnit());
                    protocolC.setTrap(protocolOutExt.getTrap());
                    protocolC.setDataType(protocolOutExt.getDataType());
                    protocolCList.add(protocolC);
                }
            }
        }
        protocolONIDto.setProtocol(protocol);
        protocolONIDto.setProtocolCList(protocolCList);
        return protocolONIDto;
    }

    /**
     * 检查协议是否已使用
     *
     * @param protocolId
     * @return
     */
    public boolean checkIsUsed(String protocolId) {
        return service.checkIsUsed(protocolId);
    }

    public StringRespDto getProtocolOutXml(String protocolId) {
        ProtocolONIDto out = getProtocolOut(protocolId);
        String xmlStr = XmlUtils.convertToXml(out, "utf-8", true);
//        System.out.println(xmlStr);
        return new StringRespDto(xmlStr);
    }

    public StringRespDto getProtocolOutCsv(String protocolId) {
        ProtocolONIDto out = getProtocolOut(protocolId);
        String uploadPath = FilenameUtils.concat(customConfig.getUploadFileDir(), "csv")
                .replaceAll("\\\\", "/");
        try {
            return new StringRespDto(SimpleCsvUtils.protocol2Csv(uploadPath, out));
        } catch (IOException e) {
            e.printStackTrace();
            return new StringRespDto("导出失败！");
        }
    }

    public List<ProtocolExt> MES2RS(List<ProtocolExt> es) {
        List<ProtocolExt> res = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(es)) {
            es.forEach((e) -> {
                res.add(this.E2R(e));
            });
        }
        return res;
    }

    @Override
    @Transactional
    public ProtocolExt save(Protocol reqDto) {
        ProtocolExt protocolExt= super.save(reqDto);

        if( "RePing".equals(reqDto.getStype().trim())){
            //添加protocl_c记录
            List<ProtocolC> protocolCList=Lists.newArrayList();

            ProtocolC pDelayed=new ProtocolC();
            pDelayed.setId(UUID.randomUUID().toString());
            pDelayed.setProtocolId(protocolExt.getId());
            pDelayed.setProtocolName(protocolExt.getName());
            pDelayed.setMid("rping-"+UUID.randomUUID().toString());
            pDelayed.setChannelCode("001");
            pDelayed.setName("延时");
            pDelayed.setUnit("ms");
            pDelayed.setDataType(0);
            pDelayed.setTrap(0);
            protocolCList.add(pDelayed);

            ProtocolC pPackage=new ProtocolC();
            pPackage.setId(UUID.randomUUID().toString());
            pPackage.setProtocolId(protocolExt.getId());
            pPackage.setProtocolName(protocolExt.getName());
            pPackage.setMid("rping-"+UUID.randomUUID().toString());
            pPackage.setChannelCode("002");
            pPackage.setName("丢包");
            pPackage.setUnit("%");
            pPackage.setDataType(0);
            pPackage.setTrap(0);
            protocolCList.add(pPackage);

            ProtocolC pShake=new ProtocolC();
            pShake.setId(UUID.randomUUID().toString());
            pShake.setProtocolId(protocolExt.getId());
            pShake.setProtocolName(protocolExt.getName());
            pShake.setMid("rping-"+UUID.randomUUID().toString());
            pShake.setChannelCode("003");
            pShake.setName("抖动");
            pShake.setUnit("ms");
            pShake.setDataType(0);
            pShake.setTrap(0);
            protocolCList.add(pShake);

            ProtocolC pNet=new ProtocolC();
            pNet.setId(UUID.randomUUID().toString());
            pNet.setProtocolId(protocolExt.getId());
            pNet.setProtocolName(protocolExt.getName());
            pNet.setMid("rping-"+UUID.randomUUID().toString());
            pNet.setChannelCode("004");
            pNet.setName("网络状态");
            pNet.setDataType(1);
            pNet.setTrap(0);
            protocolCList.add(pNet);

            protocolCService.saveProtocols(protocolCList);

        }

        return protocolExt;
    }

}